<?php

namespace app\admin\controller\fastflow\flow;

use app\admin\model\Admin;
use app\admin\model\fastflow\flow\EbillCopy;
use app\admin\model\fastflow\Signature;
use app\common\controller\Backend;
use think\Loader;
use think\Session;
use fastflow\api;

/**
 * 流程管理
 *
 * @icon fa fa-list-alt
 */
class Flow extends Backend
{
    /**
     * @var \app\admin\model\Flow
     */
    protected $model = null;
    protected $noNeedRight = [
        'flowDiagram',
        'preview',
        'detail',
        'exportWord',
        'getSelectpageWorkers',
        'getSelectpageFieldsWithComment',
        'getSelectpageOperator',
        'getStartAuthSelectOptionData',
        'getFieldsWithComment',
        'getEditAuthSelectOptionData'
    ];

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\fastflow\flow\Flow;
        $this->view->assign("statusList", $this->model->getStatusList());
    }

    public function index()
    {
        return parent::index();
    }

    /**
     * 添加
     */
    public function add()
    {
        $tableList = (new \app\admin\model\fastflow\flow\Bill())->select();
        $this->view->assign(["tableList" => $tableList, 'admin_id' => Session::get('admin')['id']]);
        return parent::add();
    }

    /*
     * 编辑
     */
    public function edit($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $tableList = (new \app\admin\model\fastflow\flow\Bill())->select();
        $this->view->assign(["tableList" => $tableList]);
        return parent::edit($ids);
    }


    /**
     * 流程设计
     */
    public function designer()
    {
        $api = new api();
        $flow_id = input('flow_id');
        $flow = $api->getFlow($flow_id);
        $this->assignconfig(['flow' => $flow]);
        $this->view->assign(['scopeList' => $api->getScope(), 'flow_id' => $flow_id]);
        return $this->view->fetch();
    }

    /**
     * 流程图预览
     */
    public function preview()
    {
        if (input('flow_id')) {
            $api = new api();
            $flow_id = input('flow_id');
            $isstart = input('isstart');
            $flow = $api->getFlow($flow_id, $isstart == 'true' ? false : true);
            $this->view->assign(['image' => $flow['image']]);
            return $this->view->fetch();
        }
    }

    /**
     * 流程图
     */
    public function flowDiagram()
    {
        if (input('bill') && input('bill_id')) {
            $api = new api();
            $bill = input('bill');
            $bill_id = input('bill_id');
            $process = $api->getProcessByBill($bill, $bill_id);
            if (!$process) {
                $this->error('该单据未发起审批', '');
            }
            $flow = $api->getFlow($process['flow_id'], true);
            if (!$flow) {
                $this->error('未找到流程，请确认流程是否已被删除', '');
            }
            $nodes = $api->getAllNodes($process['flow_id']);
            if (!$nodes) {
                $this->error('流程图不能为空，请完善流程设计', '');
            }
            $nodes_data = [];
            $condition_data = [];
            foreach ($nodes as $node) {
                $data = $node['data'];
                if ($data['type'] != 'condition') {
                    if ($data['type'] == 'step') {
                        if ($data['scope'] == 3) {
                            $data['worker'] = '读取单据' . $data['worker'] . '字段';
                        } elseif ($data['scope'] == 5) {
                            $data['worker'] = '上级审批';
                        } elseif ($data['scope'] == 6) {
                            $data['worker'] = '上一审批人动态指定';
                        } else {
                            $data['worker'] = $api->getWorkerNameStr(explode(',', $data['worker']), $data['scope']);
                        }

                    } else if ($data['type'] == 'start' || $data['type'] == 'end') {
                        $data['sign'] = '';
                        $data['back'] = '';
                        $data['checkmode'] = '';
                        $data['worker'] = '';

                    }
                    $nodes_data[] = $data;
                } else {
                    $data['flowoutcondition'] = json_decode($data['flowoutcondition'], true);
                    $data['conditioncount'] = count($data['flowoutcondition']);
                    foreach ($data['flowoutcondition'] as &$row) {
                        if (isset($row['step']) && $row['step'] != '') {
                            $step = $api->getNodeById($flow['id'], $row['step']);
                            if ($step) {
                                $row['step'] = $step['data']['name'];
                            } else {
                                $row['step'] = false;
                            }
                        }
                    }
                    $condition_data[] = $data;
                }
            }
            $this->view->assign(['image' => $flow['image'], 'flow_name' => $flow['name'], 'nodes' => $nodes_data, 'conditions' => $condition_data]);
            return $this->view->fetch();
        }
    }

    /**
     * 查看详情
     */
    public function detail()
    {
        $api = new api();
        $thread_logs = $api->getThreadLog(input('bill'), input('bill_id'));
        $bill = \app\admin\model\fastflow\flow\Bill::where(['bill_table' => input('bill')])->find();
        $bill_name = '';
        if ($bill) {
            $bill_name = $bill['bill_name'];
        }

        //4.4.2 审批详情页附加抄送记录
        $carbonModel = new \app\admin\model\fastflow\Carbon;
        foreach ($thread_logs as &$thread_log_rows) {
            foreach ($thread_log_rows as &$thread_log_row) {
                $thread_log_row['hasCarbon'] = false;
                $carbon_rows = $carbonModel->where(['current_log_id' => $thread_log_row['id']])->select();
                if ($carbon_rows) {
                    $carbon_receiver_ids = [];
                    foreach ($carbon_rows as $carbon_row) {
                        $carbon_receiver_ids[] = $carbon_row['receiver_id'];
                    }
                    $thread_log_row['hasCarbon'] = true;
                    $thread_log_row['carbon_receiver'] = $api->getWorkerNameStr($carbon_receiver_ids, 1);
                }
            }
        }
        //4.4.2 !--

        $bill_row = $api->getBillRow(input('bill'), input('bill_id'));

        $initiator = '';
        if ($bill_row) {
            $initiator_id = $bill_row['initiator_id'];
            $admin = Admin::find($initiator_id);
            if ($admin) {
                $initiator = $admin['nickname'];
            }
        }
        $bill_row_url = http_build_query(['row' => $bill_row]);
        $domain = $_SERVER['HTTP_HOST'];

        $ebill_copy_id = $this->getEbillCopyId(input('bill'), input('bill_id'));
        //查询是否有发起签章
        $hasSignature = false;
        $pdfFile = '';
        $signature = (new Signature())->where(['bill' => input('bill'), 'bill_id' => input('bill_id')])->find();
        if ($signature) {
            $hasSignature = true;
            $pdfFile = $signature['pdf_file'];
        }

        $this->view->assign(['bill' => $bill_name, 'bill_id' => input('bill_id'), 'initiator' => $initiator, 'logs' => $thread_logs, 'ebill_id' => $ebill_copy_id, 'hasSignature' => $hasSignature, 'pdfFile' => $pdfFile]);
        $this->assignconfig([
            'domain' => $domain,
            'bill' => input('bill'),
            'bill_id' => input('bill_id'),
            'controller_url' => $this->getBillControllerUrl(input('bill')),
            'ebill_id' => $ebill_copy_id,
            'bill_row' => $bill_row_url,
            'hasSignature' => $hasSignature,
        ]);

        return $this->view->fetch();
    }

    public function exportWord()
    {
        if ($this->request->isAjax()) {
            \think\Loader::addNamespace('PhpOffice\PhpWord', ADDON_PATH . 'fastflow' . DS . 'library' . DS . 'PHPWord-master' . DS . 'src' . DS . 'PhpWord' . DS);
            \think\Loader::addNamespace('Laminas\Escaper', ADDON_PATH . 'fastflow' . DS . 'library' . DS . 'laminas-escaper' . DS . 'src' . DS);
            $api = new api();
            $thread_logs = $api->getThreadLog(input('bill'), input('bill_id'));

            $dir = __DIR__ . DS . '..' . DS . '..' . DS . '..' . DS . '..' . DS . '..' . DS . 'addons' . DS . 'fastflow' . DS . 'template' . DS;
            $detailTemplate = $dir . 'detail_table_tpl.docx';
            $templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($detailTemplate);

            $bill = \app\admin\model\fastflow\flow\Bill::where(['bill_table' => input('bill')])->find();
            $bill_name = '';
            if ($bill) {
                $bill_name = $bill['bill_name'];
            }
            $bill_row = $api->getBillRow(input('bill'), input('bill_id'));
            $initiator = '';
            $bill_id = 0;
            if ($bill_row) {
                $bill_id = $bill_row['id'];
                $initiator_id = $bill_row['initiator_id'];
                $admin = Admin::find($initiator_id);
                if ($admin) {
                    $initiator = $admin['nickname'];
                }
            }

            $start_time = '';
            $log_list = [];
            foreach ($thread_logs as $day_logs) {
                foreach ($day_logs as $log) {
                    $log_list[] = $log;
                    if ($log['check_type'] == '5') {
                        $start_time = $log['createtime'];
                    }
                }
            }

            $values = [
                'bill' => $bill_name,
                'initiator' => $initiator,
                'starttime' => $start_time,
                'bill_id' => $bill_row['id'],
            ];
            $templateProcessor->setValues($values); //传值

            $domain = $_SERVER['HTTP_HOST'];
            $check_typp = ['1' => '同意', '2' => '驳回', '3' => '会签', '4' => '终止', '5' => '发起', '6' => '结束'];

            $rows = [];
            foreach ($log_list as $log) {
                $rows[] = [
                    'longtime' => $log['createtime'],
                    'step_name' => $log['step_name'],
                    'worker_name' => $log['worker_name'],
                    'check_type' => $check_typp[$log['check_type']],
                    'check_content' => $log['check_content'],
                    'file' => $log['file'] == '' ? '' : $log['file_name'] . $domain . $log['file'],
                    'agent' => $log['agent'],
                    'principal' => $log['principal']
                ];
            }
            $templateProcessor->cloneRowAndSetValues('longtime', $rows);

            $file_name = $bill_name . '(id_' . $bill_id . ')';
            $docDir = 'uploads/fastflow/detail/';
            if (!file_exists($docDir)) {
                if (!mkdir($docDir, 0777, true)) {
                    return ['code' => 0, 'msg' => '错误：无法创建文件目录'];
                }
            }
            $docPath = $docDir . $file_name . '.docx';

            $templateProcessor->saveAs($docPath);
            return ['code' => 1, 'msg' => '', 'data' => ['url' => '/' . $docPath, 'fileName' => $file_name]];

        }
    }

    public function getSelectpageWorkers()
    {
        return (new api())->getSelectpageWorkers();
    }


    public function getSelectpageFieldsWithComment()
    {
        return (new api())->getSelectpageFieldsWithComment();
    }

    public function getSelectpageOperator()
    {
        return (new api())->getSelectpageOperator();
    }

    /**
     * 保存流程图
     */
    public function saveGraph()
    {
        return (new api())->saveGraph();
    }

    private function getBillControllerUrl($bill)
    {
        $flowBillRow = (new \app\admin\model\fastflow\flow\Bill())->where(['bill_table' => $bill])->find();
        $url = Loader::parseName($flowBillRow['controller'], 0);
        $url = str_replace('/_', '/', $url);
        return $url;
    }

    public function auth($flow_id = null)
    {
        $api = new api();
        if ($this->request->isGet()) {
            if (!$flow_id) {
                $this->error('不能直接访问该页面', '');
            } else {
                $flow = $this->model->field(['id', 'name', 'bill'])->find($flow_id);
                if (!$flow) {
                    $this->error('参数错误，未找到该流程', '');
                }
                $auth_rows = $api->getAuthRow(['flow_id' => $flow['id']]);
                $startRules = null;
                $editRules = null;
                if ($auth_rows) {
                    $auth_row = $auth_rows[0];
                    $rules = json_decode($auth_row['rules'], true);
                    if (isset($rules['start'])) {
                        $startRules = $rules['start'];
                    }
                    if (isset($rules['edit'])) {
                        $editRules = $rules['edit'];
                    }
                }
                $flowArray = ['id' => $flow['id'], 'name' => $flow['name'], 'bill' => $flow['bill']];
                $this->view->assign(['flow' => $flowArray]);

                $this->assignconfig(['startRules' => $startRules, 'editRules' => $editRules, 'flow' => $flowArray]);
                return $this->view->fetch();
            }
        } elseif ($this->request->isPost()) {
            if (input('flow_id') == null || input('start/a') == null || input('edit/a') == null) {
                return ['code' => 0, 'msg' => '参数错误，请联系管理员'];
            }

            $flow_id = input('flow_id');
            $startRules = input('start/a');
            $editRules = input('edit/a');

            if (count($startRules) == 1 && isset($startRules[0])) {
                if (is_string($startRules[0])) {
                    $startRules = '';
                }
            }
            if (count($editRules) == 1 && isset($editRules[0])) {
                if (is_string($editRules[0])) {
                    $editRules = '';
                }
            }
            if (is_array($startRules)) {
                foreach ($startRules as $startRule) {
                    if ($startRule['behavior'] == '' || $startRule['control'] == '') {
                        return ['code' => 0, 'msg' => '参数错误，行为或操作不能为空'];
                    }
                }
            }
            if (is_array($editRules)) {
                foreach ($editRules as &$editRule) {
                    if ($editRule['behavior'] == '' || $editRule['control'] == '') {
                        return ['code' => 0, 'msg' => '参数错误，行为或操作不能为空'];
                    }
                    $editRule['steps'] = implode(',', $editRule['steps']);
                    $editRule['fields'] = implode(',', $editRule['fields']);
                }
            }
            $rules = [
                'start' => $startRules,
                'edit' => $editRules
            ];
            $rules = json_encode($rules, JSON_NUMERIC_CHECK);

            $auth_rows = $api->getAuthRow(['flow_id' => $flow_id]);

            if (!$auth_rows) {
                $api->addAuthRow(['flow_id' => $flow_id, 'rules' => $rules]);
            } else {
                $auth_row = $auth_rows[0];
                $auth_row['rules'] = $rules;
                $api->setAuthRow($auth_row);
            }
            return ['code' => 1, 'msg' => '单据权限配置成功'];
        }
    }

    public function getStartAuthSelectOptionData()
    {
        $behavior = [
            ['value' => 1, 'name' => '允许']
        ];
        $scope = [
            ['value' => 1, 'name' => '人员'],
            ['value' => 2, 'name' => '分组']
        ];
        $control = [
            ['value' => 1, 'name' => '发起审批']
        ];
        $data = ['behavior' => $behavior, 'scope' => $scope, 'control' => $control];
        return ['code' => 1, 'msg' => '获取成功', 'data' => $data];
    }

    public function getFieldsWithComment()
    {
        $table = input('table');
        $fileds = (new api())->getFieldsWithComment($table);
        return ['code' => 1, 'msg' => '获取成功', 'data' => $fileds];
    }

    public function getEditAuthSelectOptionData($flowid)
    {
        $behavior = [
            ['value' => 1, 'name' => '允许']
        ];
        $control = [
            ['value' => 1, 'name' => '编辑']
        ];

        $all_steps = (new api())->getAllSteps($flowid);
        $steps = [];
        foreach ($all_steps as $step) {
            if ($step['data']['type'] != 'start' && $step['data']['type'] != 'end') {
                $steps[] = ['value' => $step['id'], 'name' => $step['data']['name']];
            }
        }

        $data = ['behavior' => $behavior, 'steps' => $steps, 'control' => $control];
        return ['code' => 1, 'msg' => '获取成功', 'data' => $data];
    }

    private function getEbillCopyId($bill, $bill_id)
    {
        $ebill_copy = (new EbillCopy())->where(['bill' => $bill, 'bill_id' => $bill_id])->find();
        if ($ebill_copy) {
            $ebill_copy = $ebill_copy->toArray();
            return $ebill_copy['id'];
        }
        return null;
    }

}